home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 11
/
Cream of the Crop 11-2.iso
/
os2
/
gnucal.zip
/
gcal.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-20
|
137KB
|
4,168 lines
/*
* gcal.c: Main part which controls the extended calendar program
*
*
* Copyright (C) 1994, 1995 Thomas Esken
*
* This software doesn't claim completeness, correctness or usability.
* On principle I will not be liable for any damages or losses (implicit
* or explicit), which result from using or handling my software.
* If you use this software, you agree without any exception to this
* agreement, which binds you LEGALLY !!
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the `GNU General Public License' as published by
* the `Free Software Foundation'; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the `GNU General Public License'
* along with this program; if not, write to the:
* Free Software Foundation
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*/
static char rcsid[]="$Id: gcal.c 0.39 1995/12/20 00:03:09 tom Exp $";
/*
* Include header files
*/
#include "gcal_tai.h"
#if HAVE_ASSERT_H
# include <assert.h>
#endif
#if HAVE_CTYPE_H
# include <ctype.h>
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef GCAL_EPAGER
# if HAVE_SIGNAL_H
# include <signal.h>
# endif
# if HAVE_FCNTL_H
# include <fcntl.h>
# if !HAVE_DUP
# define dup(old) (fcntl(old, F_DUPFD, 0))
# endif
# if !HAVE_DUP2
# define dup2(old, new) (close(new), fcntl(old, F_DUPFD, new))
# endif
# endif
# if HAVE_SYS_WAIT_H
# include <sys/wait.h>
# endif
# ifndef WEXITSTATUS
# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
# endif
# ifndef WIFEXITED
# define WIFEXITED(stat_val) (((stat_val) & 0xff) == 0)
# endif
#endif /* GCAL_EPAGER */
#include "gcal.h"
/*
* Set borland/turbo-c specific MSDOS stack length in case USE_RC is defined ;<
*/
#if USE_RC
# if defined(MSDOS) && defined(__TURBOC__)
# include <dos.h>
PUBLIC Uint _stklen=0x2000;
# endif
#endif
/*
* Function prototypes
*/
#if __cplusplus
extern "C"
{
#endif
/*
************************************************** Defined in `gcal_fil.c'
*/
IMPORT FILE *
file_open __P_(( char *filename,
const Fmode_enum mode));
IMPORT void
insert_response_file __P_(( char *filename,
const char *opt_list,
int *my_argc_max,
int *my_argc,
char *my_argv[]));
IMPORT void
write_log_file __P_((const char *filename,
const Fmode_enum mode,
const char *mode_msg,
const int argc,
char *argv[]));
/*
************************************************** Defined in `gcal_hdy.c'
*/
IMPORT int
eval_holiday __P_(( int day,
const int month,
const int year,
const int wd,
const Bool forwards));
IMPORT void
print_all_holidays __P_(( Bool init_data,
const Bool detect));
/*
************************************************** Defined in `gcal_prt.c'
*/
IMPORT void
print_calendar __P_((void));
#if USE_RC
/*
************************************************** Defined in `gcal_rc.c'
*/
IMPORT void
rc_clean_flags __P_((void));
IMPORT char *
rc_get_date __P_(( char *ptr_char,
Bool *is_weekday_mode,
int *d,
int *m,
int *y,
int *n,
int *len,
char *hc,
int *hn,
int *hwd,
const char *filename,
const int line,
const char *line_buffer,
const Bool on_error_exit));
IMPORT Bool
set_dvar __P_((const char *line_buffer,
const char *filename,
const int line,
const Dvar_enum mode));
/*
************************************************** Defined in `gcal_rcu.c'
*/
IMPORT void
rc_use __P_((void));
#endif /* USE_RC */
/*
************************************************** Defined in `gcal_tty.c'
*/
IMPORT void
print_text __P_(( FILE *fp,
char *txt_line,
const Dmode_enum mode));
#if USE_PAGER
IMPORT void
get_tty_scr_size __P_((int *rows,
int *cols));
#endif
IMPORT void
get_tty_hls __P_((const char *sequence_str));
/*
************************************************** Defined in `gcal_utl.c'
*/
IMPORT void
my_extended_help __P_(( FILE *fp,
const int longopt_symbolic));
IMPORT void
my_basic_help __P_((FILE *fp));
IMPORT void
my_license __P_(( FILE *fp,
const char *prgr_id));
IMPORT void
my_version __P_(( FILE *fp,
const char *prgr_id));
IMPORT VOID_PTR
my_malloc __P_((const int amount,
const int exit_status,
const char *module_name,
const int module_line,
const char *var_name,
const int var_contents));
IMPORT VOID_PTR
my_realloc __P_(( VOID_PTR ptr_memblock,
const int amount,
const int exit_status,
const char *module_name,
const int module_line,
const char *var_name,
const int var_contents));
IMPORT void
my_error __P_((const int exit_status,
const char *module_name,
const int module_line,
const char *var_name,
const int var_contents));
IMPORT int
my_atoi __P_((const char *s));
IMPORT Bool
get_actual_date __P_((void));
IMPORT int
compare_d_m_name __P_((const char *s,
const Cmode_enum mode));
IMPORT int
weekday_of_date __P_((const int day,
const int month,
const int year));
IMPORT int
day_of_year __P_((const int day,
const int month,
const int year));
IMPORT int
days_of_february __P_((const int year));
IMPORT Bool
valid_date __P_((const int day,
const int month,
const int year));
IMPORT const char *
usage_msg __P_((void));
IMPORT void
put_longopt_description __P_((FILE *fp));
/*
************************************************** Defined in `gcal.c'
*/
EXPORT int
main __P_((int argc,
char *argv[]));
EXPORT int
eval_longopt __P_((char *longopt,
int *longopt_symbolic));
LOCAL void
rearrange_argv __P_((const char *opt_list,
int *argc,
char *argv[]));
LOCAL void
check_command_line __P_((int argc,
char *argv[]));
LOCAL void
build_month_list __P_((char *argv[]));
LOCAL void
eliminate_invalid_data __P_((void));
#if __cplusplus
}
#endif
/*
* Declare public(extern) variables
*/
#if USE_RC
IMPORT Dvar_struct rc_dvar[RC_DVAR_MAX]; /* Date variables a[=`mmdd']...z[] (`yyyy'@{a|b|...|z}[[-]<n>]) */
IMPORT int rc_period; /* Amount of period of fixed date warnings */
IMPORT int rc_elems; /* Amount of resource file entries */
IMPORT int rc_have_today_in_list; /* [-c]d */
IMPORT char *rc_adate; /* Text of modified actual date %... */
IMPORT char *rc_filename; /* Name of alternative resource file(s) -f|F<NAME[+...]> */
IMPORT char *rc_grp_sep; /* Fixed date list grouping separator [-c]g[txt] */
IMPORT Bool rc_julian_flag; /* -jc */
IMPORT Bool rc_both_dates_flag; /* -jcb */
IMPORT Bool rc_use_flag; /* -c */
IMPORT Bool rc_all_dates_flag; /* -C[] or -C[][T|W|M|Y] or -c[][T|W|M|Y] or -F<> */
IMPORT Bool rc_sort_des_flag; /* [-c]- */
IMPORT Bool rc_enable_fn_flag; /* [-c]a */
IMPORT Bool rc_enable_hda_flag; /* [-c]e */
IMPORT Bool rc_enable_hdl_flag; /* [-c]E */
IMPORT Bool rc_weekno_flag; /* [-c]k */
IMPORT Bool rc_period_list; /* [-c]l */
IMPORT Bool rc_omit_date_flag; /* [-c]o */
IMPORT Bool rc_title_flag; /* [-c]x */
IMPORT Bool rc_count_flag; /* [-c]z */
IMPORT Bool rc_period_flag; /* [-c]<<<<n>>[<d|w|+|-]>|`mmdd'|`mmww[w]'<n>> */
IMPORT Bool rc_tomorrow_flag; /* [-c]t */
IMPORT Bool rc_week_flag; /* [-c]w */
IMPORT Bool rc_month_flag; /* [-c]m */
IMPORT Bool rc_year_flag; /* [-c]y */
IMPORT Bool rc_week_year_flag; /* [-c<<n>>]w */
IMPORT Bool rc_forwards_flag; /* [-c<<n>|w|m|y>]+ */
IMPORT Bool rc_backwards_flag; /* [-c<<n>|w|m|y>]- */
IMPORT Bool rc_nzero_ldvar_flag; /* --hidden don't reset local date variables */
IMPORT Bool is_date_given; /* Is a date given in the command line? */
#endif /* USE_RC */
/*
* Define public(extern) variables
*/
PUBLIC const int dvec[]=
{
31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
}; /* Number of days in months' */
PUBLIC const int mvec[]=
{
0, 31, 59, 90, 120, 151,
181, 212, 243, 273, 304, 334
}; /* Number of past days of month */
/*
The long option table is a vector of `Lopt_struct' terminated by an element
containing a `long_name' which is zero!
all string entries in this structure must be entered in lower case letters
in ascending sort order and distinguishable in structure element `long_name'!
`symbolic_name': the symbolic name of the long option.
`long_name': the full name of the long option.
`short_name': a list of short options (maximum 5) terminated by NULL,
which order corresponds to the order of field `largs'.
`larg_mode': states whether an option requires arguments or not.
LARG_NO or 0 means:
option requires no argument, e.g. --foo
LARG_NO_OR_ONE or 1 means:
option may have an argument, e.g. --foo or --foo=BAR
LARG_ONE or 2 means:
option must have an argument, e.g. --foo=BAR
if this field is set to ARG_NO_OR_ONE and NO argument
trails the option, the `short_name[0]' contains
the default value and is returned!
`largs': a list of possible SPECIAL arguments (maximum 5) terminated
by NULL, from which only one may be selected.
if it's set to NULL only, any given argument is allowed,
otherwise only one of the listed SPECIAL arguments.
The SPECIAL arguments may be abbreviated in case this
is done unambigously.
*/
PUBLIC const Lopt_struct lopt[]=
{
/*
{ int symbolic_name, char *long_name, char *short_name[LARG_MAX], int larg_mode, char *largs[LARG_MAX]},
*/
#if USE_RC
{
SYM_DATE_VARIABLE2,
"assign",
{"v", NULL},
LARG_ONE,
{NULL}
},
#endif
{
SYM_BLOCKS,
"blocks",
{"b", NULL},
LARG_ONE,
{NULL}
},
{
SYM_CALENDAR_DATES,
"calendar-dates",
{"j", "jb", NULL},
LARG_ONE,
{"julian", "both", NULL}
},
{
SYM_LICENSE2,
"copyleft",
{"L", NULL},
LARG_NO,
{NULL}
},
{
SYM_LICENSE3,
"copyright",
{"L", NULL},
LARG_NO,
{NULL}
},
#if USE_RC
{
SYM_DATE_VARIABLE1,
"date-variable",
{"v", NULL},
LARG_ONE,
{NULL}
},
#endif
{
SYM_DEBUG,
"debug",
{"0", "1", "2", "3", "4", NULL},
LARG_NO_OR_ONE,
{"internal", "handled", "unhandled", "all", "abort", NULL}
},
#if USE_RC
{
SYM_DESC_FIXED_DATES,
"descending-fixed-dates",
{"c-", "C-", NULL},
LARG_NO_OR_ONE,
{"short", "long", NULL}
},
#endif
{
SYM_DESC_HOLIDAY_LIST,
"descending-holiday-list",
{"n-", "N-", NULL},
LARG_NO_OR_ONE,
{"long", "short", NULL}
},
{
SYM_DISABLE_HIGHLIGHTING,
"disable-highlighting",
{"Hno", NULL},
LARG_NO,
{NULL}
},
#if USE_RC
{
SYM_EXCLUDE_RC_TITLE,
"exclude-fixed-dates-list-title",
{"cx", NULL},
LARG_NO,
{NULL}
},
#endif
{
SYM_EXCLUDE_HD_TITLE,
"exclude-holiday-list-title",
{"X", NULL},
LARG_NO,
{NULL}
},
#if USE_RC
{
SYM_FIXED_DATES,
"fixed-dates",
{"jc", "jcb", NULL},
LARG_ONE,
{"julian", "both", NULL}
},
#endif
{
SYM_FORCE_HIGHLIGHTING,
"force-highlighting",
{"Hno", NULL},
LARG_NO,
{NULL}
},
#if USE_RC
{
SYM_GROUPING_TEXT,
"grouping-text",
{"cg", NULL},
LARG_NO_OR_ONE,
{NULL}
},
#endif
{
SYM_HELP,
"help",
{"h", NULL},
LARG_NO,
{NULL}
},
#if USE_RC
{
SYM_HIDDEN,
"hidden",
{NULL},
LARG_NO,
{NULL}
},
#endif
{
SYM_HIGHLIGHTING,
"highlighting",
{"H", NULL},
LARG_ONE,
{NULL}
},
{
SYM_HOLIDAY_DATES,
"holiday-dates",
{"jn", "jnb", NULL},
LARG_ONE,
{"julian", "both", NULL}
},
{
SYM_HOLIDAY_LIST,
"holiday-list",
{"n", "N", NULL},
LARG_NO_OR_ONE,
{"long", "short", NULL}
},
#if USE_RC
{
SYM_INCLUDE_CONS_NO,
"include-consecutive-number",
{"cz", NULL},
LARG_NO,
{NULL}
},
{
SYM_INCLUDE_HOLIDAY,
"include-holidays",
{"ce", "cE", NULL},
LARG_NO_OR_ONE,
{"long", "short", NULL}
},
{
SYM_INCLUDE_FILENAME,
"include-resource-file-name",
{"ca", NULL},
LARG_NO,
{NULL}
},
{
SYM_INCLUDE_TODAY,
"include-today",
{"cd", NULL},
LARG_NO,
{NULL}
},
{
SYM_INCLUDE_WEEK_NO,
"include-week-number",
{"ck", NULL},
LARG_NO,
{NULL}
},
#endif
{
SYM_LICENSE1,
"license",
{"L", NULL},
LARG_NO,
{NULL}
},
#if USE_RC
{
SYM_LIST_MODE,
"list-mode",
{"l", NULL},
LARG_NO,
{NULL}
},
{
SYM_LIST_OF_FIXED_DATES,
"list-of-fixed-dates",
{"c", "C", NULL},
LARG_NO_OR_ONE,
{"short", "long", NULL}
},
#endif
{
SYM_LONG_HELP1,
"long-help",
{"hh", NULL},
LARG_NO_OR_ONE,
{NULL}
},
{
SYM_MAIL,
"mail",
{"m", NULL},
LARG_ONE,
{NULL}
},
#if USE_RC
{
SYM_OMIT_DATE_PART,
"omit-multiple-date-part",
{"co", NULL},
LARG_NO,
{NULL}
},
#endif
#if USE_PAGER
{
SYM_PAGER,
"pager",
{"p", NULL},
LARG_NO,
{NULL}
},
#endif
#if USE_RC
{
SYM_PERIOD,
"period-of-fixed-dates",
{"c", NULL},
LARG_ONE,
{NULL}
},
{
SYM_RESOURCE_FILE,
"resource-file",
{"f", NULL},
LARG_ONE,
{NULL}
},
#endif
{
SYM_RESPONSE_FILE,
"response-file",
{"R", NULL},
LARG_ONE,
{NULL}
},
#ifdef GCAL_SHELL
{
SYM_SCRIPT_FILE,
"shell-script",
{"S", NULL},
LARG_ONE,
{NULL}
},
#endif
{
SYM_STARTING_DAY,
"starting-day",
{"s", NULL},
LARG_ONE,
{NULL}
},
{
SYM_SUPPRESS_CALENDAR,
"suppress-calendar",
{"u", NULL},
LARG_NO,
{NULL}
},
{
SYM_TYPE_OF_CALENDAR,
"type",
{"i", "i-", NULL},
LARG_ONE,
{"special", "standard", NULL}
},
{
SYM_LONG_HELP2,
"usage",
{"hh", NULL},
LARG_NO_OR_ONE,
{NULL}
},
{
SYM_VERSION,
"version",
{"V", NULL},
LARG_NO,
{NULL}
},
{
SYM_NIL,
NULL,
{NULL},
LARG_NO,
{NULL}
}
};
#ifdef GCAL_EMAIL
PUBLIC FILE *tfp=(FILE *)NULL; /* Temporary file, which is send by mailer */
#endif
PUBLIC Ml_struct month_list; /* Used if month/year is a list/range */
PUBLIC Hls_struct ehls1s; /* Effective hls 1 start (current day) */
PUBLIC Hls_struct ehls1e; /* Effective hls 1 end (current day) */
PUBLIC Hls_struct ehls2s; /* Effective hls 2 start (holiday) */
PUBLIC Hls_struct ehls2e; /* Effective hls 2 end (holiday) */
#if HAVE_ASSERT_H
PUBLIC Uint testval; /* Set to INT_MAX for checking the maximum table range */
#endif
PUBLIC int len_year_max; /* String length of the maximum year able to compute */
PUBLIC int warning_level=-1; /* --debug[=0...WARN_LVL_MAX], -1 at startup */
PUBLIC int start_day; /* -s<0,1...7|day name> */
PUBLIC int day; /* Current day */
PUBLIC int month; /* Current month */
PUBLIC int year; /* Current year */
PUBLIC int act_sec; /* Actual second */
PUBLIC int act_min; /* Actual minute */
PUBLIC int act_hour; /* Actual hour */
PUBLIC int act_day; /* Actual day */
PUBLIC int act_month; /* Actual month */
PUBLIC int act_year; /* Actual year */
PUBLIC int buf_ad; /* Buffer of actual day */
PUBLIC int buf_am; /* Buffer of actual month */
PUBLIC int buf_ay; /* Buffer of actual year */
PUBLIC int fiscal_month=MONTH_MIN; /* Starting month of a fiscal year */
PUBLIC int is_tty; /* Is output displayed on a terminal? */
PUBLIC int is_tty1; /* Is output directed to channel 1? */
PUBLIC int is_tty2; /* Is output directed to channel 2?*/
#if USE_PAGER
PUBLIC int tty_rows=-1; /* Number of tty rows, -1 at startup */
PUBLIC int tty_cols=-1; /* Number of tty columns, -1 at startup */
#endif
PUBLIC int out_rows; /* Number of month rows of a year calendar */
PUBLIC int out_cols; /* Number of month columns of ... */
PUBLIC int fmt_len; /* Format lenght of a standard/julian/both day */
PUBLIC int is_leap_year; /* Is current year a leap year? */
PUBLIC int holiday_vector[MONTH_MAX][MONTH_MAX]; /* Stores the holiday dates */
PUBLIC int len_prgr_name; /* Length of actual program name */
PUBLIC char s[MAXLEN+1]; /* General purpose text buffer */
PUBLIC char s2[MAXLEN+1]; /* General purpose text buffer */
PUBLIC char s3[MAXLEN+1]; /* General purpose text buffer */
PUBLIC char *prgr_name=(char *)NULL; /* Stores the actual program name */
#ifdef GCAL_EPAGER
PUBLIC char *ext_pager=(char *)NULL; /* Name of external pager program */
#endif
PUBLIC Bool suppr_cal_flag=FALSE; /* -u */
PUBLIC Bool highlight_flag=TRUE; /* -H<yes> or -H<no> */
PUBLIC Bool cal_julian_flag=FALSE; /* -j */
PUBLIC Bool cal_both_dates_flag=FALSE; /* -jb */
PUBLIC Bool holiday_flag=FALSE; /* -n|N */
PUBLIC Bool hd_legal_days_only=FALSE; /* -N */
PUBLIC Bool hd_sort_des_flag=FALSE; /* [-n|N]- */
PUBLIC Bool hd_julian_flag=FALSE; /* -jn */
PUBLIC Bool hd_both_dates_flag=FALSE; /* -jnb */
PUBLIC Bool hd_title_flag=TRUE; /* -X */
PUBLIC Bool is_fiscal_year=FALSE; /* ':' char found in argument (`mm':`yyyy') */
PUBLIC Bool is_3month_mode=FALSE; /* Argument is "." or ".+" or "+-" */
PUBLIC Bool is_3month_mode2=FALSE; /* Argument is ".." -> current quarter of actual year */
PUBLIC Bool is_ext_year=FALSE; /* Is extended year mode? */
PUBLIC Bool is_ext_list=FALSE; /* Is extended list mode? */
PUBLIC Bool is_ext_range=FALSE; /* Is extended range mode? */
#if USE_GER
PUBLIC Bool special_calsheet_flag=FALSE;/* -i */
#else /* !USE_GER */
PUBLIC Bool special_calsheet_flag=TRUE; /* -i */
#endif /* !USE_GER */
#if USE_HLS
PUBLIC Bool emu_hls=FALSE; /* Must we emulate the highlighting sequences? */
#else /* !USE_HLS */
PUBLIC Bool emu_hls=TRUE; /* Must we emulate the highlighting sequences? */
#endif /* !USE_HLS */
#if USE_PAGER
PUBLIC Bool pager_flag=FALSE; /* -p */
#endif
/*
Define local(static) variables
*/
#ifdef GCAL_EPAGER
LOCAL pid_t child_pid; /* Id of child process of external pager */
LOCAL int pipe_fd[2]; /* Pipe file descriptors */
LOCAL int sys_fd[2]; /* Buffer of system file descriptors 0 and 1 */
#endif
LOCAL int lopt_id; /* The index value of a long option */
#ifdef GCAL_EMAIL
LOCAL char *email_adr=(char *)NULL; /* Email address gcal's output is send to */
#endif
#ifdef GCAL_SHELL
LOCAL char *shl_filename=(char *)NULL; /* File name of shell script to write -S<NAME> */
#endif
LOCAL char *rsp_filename=(char *)NULL; /* Name of response file to write -R<NAME> */
LOCAL char *hl_seq=(char *)NULL; /* Text containing user defined highlighting sequences -H<> */
LOCAL Bool license_flag=FALSE; /* -L */
LOCAL Bool version_flag=FALSE; /* -V */
LOCAL Bool help_flag=FALSE; /* -? | -h */
LOCAL Bool ext_help_flag=FALSE; /* -?? | -hh */
LOCAL Bool year_flag=FALSE; /* -b<1|2|3|4|6|12> */
LOCAL Bool switch_back_flag=FALSE; /* [-i]- */
LOCAL Bool show_calendar=TRUE; /* Must we display the calendar? */
/*
Program entry point
*/
#ifdef ANSI_PROTO
PUBLIC int
main (int argc,
char *argv[])
#else /* !ANSI_PROTO */
PUBLIC int
main (argc, argv)
int argc;
char *argv[];
#endif /* !ANSI_PROTO */
/*
Perform the program =8^)
*/
{
auto int my_argc_max=MY_ARGC_MAX;
auto int my_argc=1;
auto int i=0;
#if USE_RC
# ifdef GCAL_SHELL
# ifdef GCAL_EMAIL
static const char *these_short_options_need_args="FHRSbfmsv";
# else /* !GCAL_EMAIL */
static const char *these_short_options_need_args="FHRSbfsv";
# endif /* !GCAL_EMAIL */
# else /* !GCAL_SHELL */
# ifdef GCAL_EMAIL
static const char *these_short_options_need_args="FHRbfmsv";
# else /* !GCAL_EMAIL */
static const char *these_short_options_need_args="FHRbfsv";
# endif /* !GCAL_EMAIL */
# endif /* !GCAL_SHELL */
#else /* !USE_RC */
# ifdef GCAL_SHELL
# ifdef GCAL_EMAIL
static const char *these_short_options_need_args="HRSbms";
# else /* !GCAL_EMAIL */
static const char *these_short_options_need_args="HRSbs";
# endif /* !GCAL_EMAIL */
# else /* !GCAL_SHELL */
# ifdef GCAL_EMAIL
static const char *these_short_options_need_args="HRbms";
# else /* !GCAL_EMAIL */
static const char *these_short_options_need_args="HRbs";
# endif /* !GCAL_EMAIL */
# endif /* !GCAL_SHELL */
#endif /* !USE_RC */
auto char **my_argv=(char **)NULL;
#ifdef GCAL_EMAIL
auto char *tfn=(char *)NULL;
#endif
auto char *ptr_char;
/*
Compute the string length of the maximum year able to compute
*/
sprintf(s, "%d", YEAR_MAX);
len_year_max = (int)strlen(s);
#if HAVE_ASSERT_H
/*
Perform some assertations for safe program operation...
*/
testval = ~0;
testval >>= 1;
/*
Check if value for maximum number of table entries
fits to the positive range of a signed int (INT_MAX)!!
*/
assert(my_argc_max>0);
assert((Uint)my_argc_max<=testval);
# if DEBUG
assert(len_year_max<11);
assert(len_year_max>0);
assert(YEAR_MAX>=YEAR_MIN);
assert(MONTH_MAX==12);
assert(CENTURY==1900);
/*
For safe program operation, BUF_LEN must be 1 minimum!!
*/
assert(BUF_LEN>=1);
/*
For safe program operation, MAXLEN must be 256 minimum!!
*/
assert(MAXLEN>=256);
assert(strlen(PRGR_NAME)<7);
assert(strlen(PRGR_NAME)>0);
assert(strlen(VERSION_NO)>0);
assert(MY_ARGC_MAX>1);
assert(HD_ELEMS_MAX>0);
# endif
#endif /* HAVE_ASSERT_H */
/*
Test if program output is redirected/piped
*/
#if USE_PAGER
is_tty1 = isatty(1);
is_tty2 = isatty(2);
is_tty = ( is_tty1
&& is_tty2);
# ifdef GCAL_EPAGER
if (is_tty)
{
/*
Store the sys-stdin/sys-stdout file descriptors
*/
dup2(0, sys_fd[0]);
dup2(1, sys_fd[1]);
}
# endif
#else /* !USE_PAGER */
is_tty = (int)TRUE;
#endif /* !USE_PAGER */
/*
Detect the own program name
*/
strncpy(s3, argv[0], MAXLEN+1);
s3[MAXLEN] = '\0';
#ifdef SUFFIX_SEP
/*
Eliminate version suffix under VMS
*/
ptr_char = strrchr(s3, *SUFFIX_SEP);
if (ptr_char != (char *)NULL)
*ptr_char = '\0';
#endif
len_prgr_name = (int)strlen(s3);
#ifdef DJG
ptr_char = strrchr(s3, *DIR2_SEP);
#else /* !DJG */
ptr_char = strrchr(s3, *DIR_SEP);
#endif /* !DJG */
if (ptr_char != (char *)NULL)
{
ptr_char++;
len_prgr_name = (int)strlen(ptr_char);
}
else
ptr_char = s3;
if (tolower('A') == 'a')
{
auto char *buf_ptr_char=ptr_char;
for ( ; *ptr_char ; ptr_char++)
*ptr_char = (char)tolower(*ptr_char);
ptr_char = buf_ptr_char;
}
/*
Suppress .exe suffix for MSDOS, OS/2 and VMS
*/
if ( (len_prgr_name > 4)
&& !strcmp(ptr_char+len_prgr_name-4, ".exe"))
{
len_prgr_name -= 4;
*(ptr_char + len_prgr_name) = '\0';
}
/*
Maximum length of actual program name is 6 characters
*/
if (len_prgr_name > 6)
{
len_prgr_name = 6;
*(ptr_char + len_prgr_name) = '\0';
}
prgr_name = (char *)my_malloc (len_prgr_name+1,
124, __FILE__, __LINE__ -1,
"prgr_name", 0);
strcpy(prgr_name, ptr_char);
/*
Initial memory allocation for `my_argv[]'
*/
my_argv = (char **)my_malloc (MY_ARGC_MAX*sizeof(char *),
124, __FILE__, __LINE__ -1,
"my_argc", MY_ARGC_MAX);
#if !defined(AMIGA) || defined(__GNUC__)
/*
Detect whether the GCAL environment variable is set
*/
ptr_char = getenv(ENV_VAR_GCAL);
if (ptr_char != (char *)NULL)
{
if (*ptr_char)
{
/*
GCAL environment variable defined and not empty: copy the OPTIONS
expanded @file argument or actual date modifier %... argument only;
found in environment variable GCAL; into private `my_argv'
*/
while (MY_ISSPACE(*ptr_char))
ptr_char++;
i = 0;
while (*ptr_char)
{
if (i < MAXLEN)
s[i++] = *ptr_char++;
if ( !*ptr_char
|| MY_ISSPACE(*ptr_char))
{
s[i] = '\0';
if ( *s == *SWITCH
|| *s == *SWITCH2
# if USE_RC
|| *s == RC_ADATE_CHAR
# endif
|| *s == RSP_CHAR)
{
/*
Avoid one or two letter combinitions of '-', '/', '%' or '@' characters only!
*/
if ( i == 1
|| ( (i == 2)
&& ( s[1] == *SWITCH
# if USE_RC
|| s[1] == RC_ADATE_CHAR
# endif
|| s[1] == *SWITCH2)))
; /* Void, don't allocate memory */
else
{
if (*s == RSP_CHAR)
{
/*
Try to manage a response file "@file" argument given
in environment variable GCAL.
*/
strncpy(s3, s+1, MAXLEN+1);
s3[MAXLEN] = '\0';
insert_response_file (s3, these_short_options_need_args,
&my_argc_max, &my_argc, my_argv);
}
else
{
/*
Ok, argument is an option or an actual date modifier %...
*/
if ( ( *s == *SWITCH
|| *s == *SWITCH2)
&& (s[1] != *SWITCH))
{
/*
Short-style option found
*/
if (strchr(these_short_options_need_args, s[1]) != (char *)NULL)
{
/*
Short-style option requires an argument, which could be separated
by whitespace characters from the option character; respect this!
this means all separating whitespace characters between the
option character and argument will be eliminated.
*/
while (MY_ISSPACE(*ptr_char))
ptr_char++; /* Skip the separating whitespace characters. */
/*
Store needed argument of option adjacent to option character.
*/
while ( (i < MAXLEN)
&& *ptr_char
&& !MY_ISSPACE(*ptr_char))
s[i++] = *ptr_char++;
}
s[i] = '\0';
}
if (my_argc >= my_argc_max)
{
# if HAVE_ASSERT_H
/*
Check if value for maximum number of table entries
fits to the positive range of a signed int(INT_MAX)!!
*/
assert((Uint)my_argc_max+MY_ARGC_MAX<=testval);
# endif
/*
Resize the table
*/
my_argc_max += MY_ARGC_MAX;
my_argv = (char **)my_realloc (my_argv, my_argc_max*sizeof(char *),
124, __FILE__, __LINE__ -1,
"my_argc", my_argc_max);
}
my_argv[my_argc] = (char *)my_malloc (i+1,
124, __FILE__, __LINE__ -1,
"my_argc", my_argc);
strcpy(my_argv[my_argc++], s);
}
}
while (MY_ISSPACE(*ptr_char))
ptr_char++;
i = 0;
}
else
if (i)
{
/*
Error, argument is a command
*/
# if USE_GER
fprintf(stderr, "%s: Kommando in Umgebungsvariable `"ENV_VAR_GCAL
"' angegeben -- %s\n", prgr_name, s);
# else /* !USE_GER */
fprintf(stderr, "%s: command in environment variable `"ENV_VAR_GCAL
"' found -- %s\n", prgr_name, s);
# endif /* !USE_GER */
fprintf(stderr, "%s\n", usage_msg ());
put_longopt_description (stderr);
S_NEWLINE(stderr);
exit(126);
}
}
}
}
}
#endif /* !AMIGA || __GNUC__ */
/*
Now insert/append the "arguments" of command line
into private `my_argv'
*/
while (argc > 1)
{
++argv;
/*
Preload contents of response files and don't place this option
text itself in private `my_argc' command line options vector!
*/
if (**argv == RSP_CHAR)
{
/*
Try to manage a response file "@file" argument given in command line.
*/
strncpy(s3, *argv+1, MAXLEN+1);
s3[MAXLEN] = '\0';
insert_response_file (s3, these_short_options_need_args,
&my_argc_max, &my_argc, my_argv);
}
else
{
register int len=(int)strlen(*argv);
/*
Avoid one or two letter combinitions of '-', '/' or '%' characters only!
*/
if ( ( (len == 1)
&& ( **argv == *SWITCH
#if USE_RC
|| **argv == RC_ADATE_CHAR
#endif
|| **argv == *SWITCH2))
|| ( (len == 2)
&& ( **argv == *SWITCH
#if USE_RC
|| **argv == RC_ADATE_CHAR
#endif
|| **argv == *SWITCH2)
&& ( *(*argv+1) == *SWITCH
#if USE_RC
|| *(*argv+1) == RC_ADATE_CHAR
#endif
|| *(*argv+1) == *SWITCH2)))
; /* Void, don't allocate memory */
else
{
if (my_argc >= my_argc_max)
{
#if HAVE_ASSERT_H
/*
Check if value for maximum number of table entries
fits to the positive range of a signed int(INT_MAX)!!
*/
assert((Uint)my_argc_max+MY_ARGC_MAX<=testval);
#endif
/*
Resize the table
*/
my_argc_max += MY_ARGC_MAX;
my_argv = (char **)my_realloc (my_argv, my_argc_max*sizeof(char *),
124, __FILE__, __LINE__ -1,
"my_argc", my_argc_max);
}
my_argv[my_argc] = (char *)my_malloc (len+1,
124, __FILE__, __LINE__ -1,
"my_argc", my_argc);
strcpy(my_argv[my_argc++], *argv);
}
}
argc--;
}
/*
Building of private `*my_argv[]' is complete, so check first whether
warning/debug option (--debug[=0...WARN_LVL_MAX]) is given (needed to
set correct warning level in case global date variable definitions or
operations follow) and then check whether global date variable
definitions/operations -v<> are given so we can reference them
in actual date modifier, e.g., %`yyyy'@`dvar'[[-]<n>[`ww[w]']]
*/
if (my_argc > 1)
{
auto int j;
/*
Now it's time to rearrange `*my_argv[]', so all short-style options
with needed argument like `-X foo' are concatenated to `-Xfoo'.
*/
rearrange_argv (these_short_options_need_args, &my_argc, my_argv);
i = 1;
while (i < my_argc)
{
ptr_char = my_argv[i];
if ( *ptr_char == *SWITCH
|| *ptr_char == *SWITCH2)
{
ptr_char++;
if (*ptr_char == *SWITCH)
{
/*
Long option given;
convert it to an according short option
*/
ptr_char++;
strncpy(s3, ptr_char, MAXLEN+1);
s3[MAXLEN] = '\0';
/*
Set only option part to lower case
*/
j = 0;
while ( s3[j]
&& (s3[j] != *LARG_SEP))
{
s3[j] = (char)tolower(s3[j]);
j++;
}
if (!eval_longopt (s3, &lopt_id))
ptr_char = s3;
else
/*
Error in given long option detected;
skip this long option only!
*/
ptr_char = s3 + strlen(s3);
}
else
lopt_id = SYM_NIL;
if (lopt_id == SYM_DEBUG)
warning_level = my_atoi (ptr_char);
#if USE_RC
else
if (*ptr_char == 'v')
{
ptr_char++;
/*
Global date variable definition found
(e.g. -va=1227:b=0514:c=a...) so try to scan
argument and store found `mmdd' dates in
date variable vector
*/
while (*ptr_char)
{
/*
Split the colon separated list of date variables
*/
j = 0;
while ( *ptr_char
&& (*ptr_char != *SEP)
&& (j < MAXLEN))
s[j++] = *ptr_char++;
s[j] = '\0';
if (!set_dvar (s, RC_INTERNAL_TXT, 0, GLobal))
/*
Error, unable to store date variable
*/
my_error (114, "", 0, s, 0);
if (*ptr_char)
ptr_char++;
}
}
#endif /* USE_RC */
}
/*
Stop processing if first command is found
*/
if ( (*my_argv[i] != *SWITCH)
#if USE_RC
&& (*my_argv[i] != RC_ADATE_CHAR)
#endif
&& (*my_argv[i] != *SWITCH2))
break;
i++;
}
}
#if USE_RC
/*
Check whether actual date modifier %... is given
*/
if (my_argc > 1)
{
i = 1;
while (i < my_argc)
{
if (*my_argv[i] == RC_ADATE_CHAR)
rc_adate = my_argv[i] + 1;
/*
Stop processing if first command is found
*/
if ( (*my_argv[i] != *SWITCH)
&& (*my_argv[i] != *SWITCH2)
&& (*my_argv[i] != RC_ADATE_CHAR))
break;
i++;
}
}
/*
Read the internal system date
*/
if (!get_actual_date ())
{
/*
Error, invalid actual date modifier %... given
*/
# if USE_GER
fprintf(stderr, "%s: Ung"UE"ltiges Datum angegeben -- %c%s\n",
prgr_name, RC_ADATE_CHAR, rc_adate);
# else /* !USE_GER */
fprintf(stderr, "%s: invalid date given -- %c%s\n",
prgr_name, RC_ADATE_CHAR, rc_adate);
# endif /* !USE_GER */
fprintf(stderr, "%s\n", usage_msg ());
put_longopt_description (stderr);
S_NEWLINE(stderr);
exit(126);
}
#else /* !USE_RC */
(void)get_actual_date ();
#endif /* !USE_RC */
is_leap_year = (days_of_february (act_year) == 29);
#ifdef GCAL_EPAGER
if (is_tty)
{
auto FILE *fp=(FILE *)NULL;
/*
Try to detect the external pager program in a safe way
*/
ptr_char = getenv(ENV_VAR_PAGER);
if (ptr_char != (char *)NULL)
{
if (*ptr_char)
{
while (MY_ISSPACE(*ptr_char))
ptr_char++;
strncpy(s3, ptr_char, MAXLEN+1);
s3[MAXLEN] = '\0';
if (*ptr_char != *DIR_SEP)
{
ptr_char = strrchr(s3, *DIR_SEP);
if (ptr_char != (char *)NULL)
ptr_char++;
else
ptr_char = s3;
}
ext_pager = (char *)my_malloc (strlen(ptr_char)+1,
124, __FILE__, __LINE__ -1,
"ext_pager", 0);
strcpy(ext_pager, ptr_char);
i = 0;
while ( ext_pager[i]
&& !MY_ISSPACE(ext_pager[i]))
i++;
ext_pager[i] = '\0';
if (*ext_pager == *DIR_SEP)
/*
Absolute pager name given, search program directly
*/
fp = fopen(ext_pager, "r");
else
{
/*
Relative pager name given, search program in PATH
*/
strncpy(s3, ext_pager, MAXLEN+1);
s3[MAXLEN] = '\0';
fp = file_open (s3, COmmon);
}
if (fp == (FILE *)NULL)
{
free(ext_pager);
ext_pager = (char *)NULL;
}
}
}
if (ext_pager == (char *)NULL)
{
strncpy(s3, PAGER_PROG, MAXLEN+1);
s3[MAXLEN] = '\0';
fp = file_open (s3, COmmon);
if (fp != (FILE *)NULL)
{
ext_pager = PAGER_PROG;
fclose(fp);
}
else
{
strncpy(s3, PAGER2_PROG, MAXLEN+1);
s3[MAXLEN] = '\0';
fp = file_open (s3, COmmon);
if (fp != (FILE *)NULL)
{
ext_pager = PAGER2_PROG;
fclose(fp);
}
}
}
if (ext_pager != (char *)NULL)
{
/*
We work unbuffered in this case so we have to flush stdout buffer first
*/
fflush(stdout);
/*
Open unnamed pipe
*/
if (pipe(pipe_fd) < 0)
/*
Error, pipe() fails
*/
my_error (110, __FILE__, __LINE__ -4, "pipe()", 0);
/*
Ignore SIGPIPE signal
*/
signal(SIGPIPE, SIG_IGN);
}
}
#endif /* GCAL_EPAGER */
/*
Check and evaluate the command line arguments and detect,
whether the extended year/list/range mode is wanted
*/
check_command_line (my_argc, my_argv);
#ifdef GCAL_EMAIL
/*
In case gcal's output must be send to a user via Email:
create and open temporary file
*/
if (email_adr != (char *)NULL)
{
tfn = tmpnam(NULL);
if (tfn == (char *)NULL)
my_error (111, "", 0, email_adr, 0);
tfp = fopen(tfn, "w");
if (tfp == (FILE *)NULL)
my_error (111, "", 0, email_adr, 0);
is_tty = (int)FALSE;
# if USE_GER
fprintf(tfp, "Subject: Post von %s "
"(%04d/%02d/%02d %02d"TIME_SEP"%02d"TIME_SEP"%02d)\n\n",
prgr_name, buf_ay, buf_am, buf_ad, act_hour, act_min, act_sec);
# else /* !USE_GER */
fprintf(tfp, "Subject: Mail from %s "
"(%04d/%02d/%02d %02d"TIME_SEP"%02d"TIME_SEP"%02d)\n\n",
prgr_name, buf_ay, buf_am, buf_ad, act_hour, act_min, act_sec);
# endif /* !USE_GER */
}
#endif /* GCAL_EMAIL */
/*
Check whether month calendar output is wanted
in case no explicit date is given in command line
*/
if (switch_back_flag)
special_calsheet_flag = (Bool)!special_calsheet_flag;
/*
Do we have to suppress the output of a month calendar in case only
the -n|N[-] flag (display eternal holiday list) is found and/or
only the -c[] flag (display fixed date warnings) is found?
*/
if ( !year
&& !month
&& ( holiday_flag
#if USE_RC
|| rc_use_flag
#endif
)
#if USE_GER
&& !special_calsheet_flag
#else /* !USE_GER */
&& special_calsheet_flag
#endif /* !USE_GER */
&& ( !start_day
|| ( (start_day < DAY_MIN)
#if USE_RC
&& rc_use_flag
#endif
))
&& !switch_back_flag
&& !year_flag)
show_calendar = FALSE;
#if USE_RC
/*
Check whether an explicit date is given in command line
*/
is_date_given = (Bool)( month
|| year
|| is_fiscal_year);
#endif
/*
Check whether the arguments of command line are valid
*/
eliminate_invalid_data ();
/*
Get the highlighting sequences of the terminal
*/
get_tty_hls (hl_seq);
#if USE_PAGER
/*
No program output yet, so if the paging option is wanted:
set the standard stream buffers to unbuffered mode
and get actual settings of the tty
*/
if ( is_tty1
&& is_tty2
# ifdef GCAL_EPAGER
&& (ext_pager == (char *)NULL)
# endif
&& pager_flag)
{
setbuf(stdout, (char *)NULL);
setbuf(stdin, (char *)NULL);
get_tty_scr_size (&tty_rows, &tty_cols);
}
#endif /* USE_PAGER */
/*
Log contents of command line:
i.e. check whether a response file must be written
*/
if (rsp_filename != (char *)NULL)
write_log_file (rsp_filename, REsponse, RESPONSE_TXT, my_argc, my_argv);
#ifdef GCAL_SHELL
/*
Log contents of command line:
i.e. check whether a shell script must be written
*/
if (shl_filename != (char *)NULL)
write_log_file (shl_filename, SCript, SCRIPT_TXT, my_argc, my_argv);
#endif /* GCAL_SHELL */
#ifdef GCAL_EPAGER
if ( is_tty1
&& is_tty2
&& pager_flag
&& (ext_pager != (char *)NULL))
{
child_pid = fork();
switch (child_pid)
{
case -1:
/*
Error, fork() fails
*/
my_error (110, __FILE__, __LINE__ -7, "fork()", 0);
case 0:
/*
Child process (read from pipe):
connect pipe-stdin to sys-stdin in a safe way
and launch external pager
*/
close(pipe_fd[1]);
if (pipe_fd[0])
{
close(0);
dup(pipe_fd[0]);
close(pipe_fd[0]);
}
execlp(ext_pager, ext_pager, (char *)NULL);
/*
Error, execlp() fails (this line should never be executed)
*/
sprintf(s, "execlp(%s)", ext_pager);
my_error (110, __FILE__, __LINE__ -5, s, 0);
default:
/*
Parent process (write to pipe):
connect pipe-stdout to sys-stdout in a safe way
and initiate action
*/
close(pipe_fd[0]);
if (pipe_fd[1] != 1)
{
close(1);
if (!dup(pipe_fd[1]))
{
dup(pipe_fd[1]);
close(0);
}
close(pipe_fd[1]);
}
}
}
#endif /* GCAL_EPAGER */
/*
And now display the calendar
*/
if (show_calendar)
print_calendar ();
else
/*
Only the -n|N[-] flag (display eternal holiday list) is found and/or
only the -c[] flag (display fixed date warnings) is found, display
these list(s) without/omitting a leading month calendar
*/
{
register int tmp_ad=act_day;
is_leap_year = (days_of_february (year) == 29);
if (is_fiscal_year)
fiscal_month = *month_list.month;
if (cal_julian_flag)
act_day = day_of_year (tmp_ad, act_month, act_year);
if ( ( (year == EASTER_MIN-1)
&& (fiscal_month > MONTH_MIN))
|| ( (year >= EASTER_MIN)
&& (year <= EASTER_MAX)))
print_all_holidays (FALSE, TRUE);
if (cal_julian_flag)
act_day = tmp_ad;
}
/*
If simple month-/year mode is active...
*/
if (!month_list.month[1])
{
if ( is_fiscal_year
|| ( holiday_flag
&& !show_calendar))
month = 0;
#if USE_RC
if (rc_use_flag)
rc_use ();
#endif
if (holiday_flag)
{
if ( ( (year == EASTER_MIN-1)
&& (fiscal_month == 1))
|| year < EASTER_MIN-1
|| year > EASTER_MAX)
/*
Error, invalid year given for computation of Easter Sunday's date
*/
my_error (125, "", 0, "", 0);
print_all_holidays (FALSE, FALSE);
}
}
#ifdef GCAL_EPAGER
if ( is_tty1
&& is_tty2
&& pager_flag
&& (ext_pager != (char *)NULL))
{
/*
We work unbuffered in this case so we have to flush stdout buffer
for showing all contents of it
*/
fflush(stdout);
/*
And reconnect the sys-stdin/sys-stdout file descriptors
*/
close(0);
dup(sys_fd[0]);
close(1);
dup(sys_fd[1]);
/*
And wait until child has performed all action
*/
while (wait((pid_t *)NULL) != child_pid)
;
/*
Reset SIGPIPE signal
*/
signal(SIGPIPE, SIG_DFL);
}
#endif /* GCAL_EPAGER */
#ifdef GCAL_EMAIL
/*
If mailing option is selected:
close temporary file, redirect it to mailer and then erase it
*/
if (email_adr != (char *)NULL)
{
if (fclose(tfp) == EOF)
my_error (111, "", 0, email_adr, 0);
sprintf(s, MAIL_PRGR" %s "REDIRECT" %s", email_adr, tfn);
if (system(s))
{
/*
If the shell reports a `mail' exit status not equal 0,
first try to erase the temporary file (or let it be if
it fails) and terminate gcal with error message
*/
(void)unlink(tfn);
my_error (111, "", 0, email_adr, 0);
}
/*
Ignore any errors...
*/
(void)unlink(tfn);
}
#endif
#if USE_RC
if ( rc_use_flag
&& !rc_elems)
return(1);
#endif
return(0);
}
#ifdef ANSI_PROTO
PUBLIC int
eval_longopt (char *longopt,
int *longopt_symbolic)
#else /* !ANSI_PROTO */
PUBLIC int
eval_longopt (longopt, longopt_symbolic)
char *longopt;
int *longopt_symbolic;
#endif /* !ANSI_PROTO */
/*
Evaluates a long option and returns -2...0 on success, +1...+6 if fails:
-2 == given `longopt' successfully parsed and completed `long_name' with argument returned.
-1 == given `longopt' successfully parsed and completed `long_name' only returned.
0 == given `longopt' successfully parsed and corresponding `short_name' returned.
+1 == given `longopt' is ambiguous (not distinguishable).
+2 == given `longopt' is unknown.
+3 == given `longopt' requires no argument.
+4 == given `longopt' requires an argument.
+5 == given `longopt' with invalid argument.
+6 == given `longopt' with ambiguous argument.
if success and `short_name[0]' isn't set to NULL, the delivered `longopt'
is converted to an according `short_name' (UN*X-style) option and returned,
otherwise `longopt' is returned unmodified.
if success and `short_name[0]' is set to NULL, return the completed
`long_name' (with possibly trailing arguments) instead.
`longopt_symbolic' is either set to SYM_NIL if given `longopt' isn't member
of field `long_name' of `lopt' structure or to the according SYM_???.
*/
{
auto const Lopt_struct *ptr_lopt=&lopt[0];
*longopt_symbolic = SYM_NIL;
if (*longopt >= *ptr_lopt->long_name)
{
/*
Check whether first character of `longopt' can be found in `lopt' structure member `long_name'.
*/
while (*ptr_lopt->long_name < *longopt)
{
ptr_lopt++;
if (ptr_lopt->long_name == NULL)
break;
}
if (ptr_lopt->long_name != NULL)
{
if (*ptr_lopt->long_name == *longopt)
{
auto const Lopt_struct *ptr2_lopt=ptr_lopt+1;
register int len_longopt=(int)strlen(longopt);
auto Bool larg_sep_found;
auto Bool ok=FALSE;
if (strchr(longopt, *LARG_SEP) != NULL)
len_longopt -= (int)strlen(strchr(longopt, *LARG_SEP));
/*
First character of `longopt' is found in `lopt' structure member `long_name';
now check for the complete long name or a significant abbreviation of it.
*/
while ( !ok
&& (ptr_lopt->long_name != NULL))
{
if ( !strncmp(ptr_lopt->long_name, longopt, len_longopt)
&& !strncmp(ptr2_lopt->long_name, longopt, len_longopt))
/*
Error, `longopt' is ambiguous (not distinguishable).
*/
return(1);
if (strncmp(ptr_lopt->long_name, longopt, len_longopt))
{
ptr_lopt++;
if (ptr_lopt->long_name != NULL)
ptr2_lopt++;
if (ptr2_lopt->long_name == NULL)
if (!strncmp(ptr_lopt->long_name, longopt, len_longopt))
ok = TRUE;
}
else
ok = TRUE;
}
if (!ok)
/*
Error, `longopt' not found (contains a spelling mistake).
*/
return(2);
larg_sep_found = (Bool)(((int)strlen(longopt)-len_longopt) ? TRUE : FALSE);
if ( larg_sep_found
&& (ptr_lopt->larg_mode == LARG_NO))
{
*longopt_symbolic = ptr_lopt->symbolic_name;
/*
Error, `longopt' requires no argument.
*/
return(3);
}
if ( !larg_sep_found
&& (ptr_lopt->larg_mode > LARG_NO_OR_ONE))
{
*longopt_symbolic = ptr_lopt->symbolic_name;
/*
Error, `longopt' requires an argument.
*/
return(4);
}
/*
Valid `longopt' found.
*/
if ( ptr_lopt->larg_mode == LARG_NO
|| ( (ptr_lopt->larg_mode == LARG_NO_OR_ONE)
&& !larg_sep_found))
{
/*
`longopt' requires NO argument (e.g. foo);
return the FIRST `short_name' of `lopt' structure if its
not set to NULL, otherwise return the completed `long_name'.
*/
if (ptr_lopt->short_name[0] == NULL)
{
strcpy(longopt, ptr_lopt->long_name);
*longopt_symbolic = ptr_lopt->symbolic_name;
return(-1);
}
strcpy(longopt, ptr_lopt->short_name[0]);
}
else
{
auto char *ptr_char=longopt+len_longopt+1;
auto char *larg_longopt;
/*
`longopt' must have ONE trailing argument (e.g. foo=BAR);
return the CORRESPONDING `short_name' stored in `lopt' structure.
*/
if (!*ptr_char)
{
*longopt_symbolic = ptr_lopt->symbolic_name;
/*
Error, `longopt' isn't trailed by an argument.
*/
return(4);
}
larg_longopt = (char *)my_malloc (strlen(longopt)-len_longopt,
124, __FILE__, __LINE__ -1,
"larg_longopt", 0);
strcpy(larg_longopt, ptr_char);
if (ptr_lopt->largs[0] == NULL)
{
/*
Process ANY argument given.
*/
if (ptr_lopt->short_name[0] == NULL)
{
/*
Return the completed `long_name' with given argument;
the format of returned `longopt' is like: foo=BAR
*/
strcpy(longopt, ptr_lopt->long_name);
strcat(longopt, LARG_SEP);
strcat(longopt, larg_longopt);
*longopt_symbolic = ptr_lopt->symbolic_name;
return(-2);
}
/*
Return the corresponding `short_name' with given argument;
the format of returned `longopt' is like: fooBAR
*/
strcpy(longopt, ptr_lopt->short_name[0]);
strcat(longopt, larg_longopt);
}
else
{
register int i=0;
/*
Process SPECIAL argument given.
*/
ok = FALSE;
/*
Set complete `larg_longopt' to lower case.
*/
while (larg_longopt[i])
{
larg_longopt[i] = (char)tolower(larg_longopt[i]);
i++;
}
i = 0;
ptr_char = ptr_lopt->largs[i++];
while ( !ok
&& (ptr_char != NULL))
{
if (*ptr_char == *larg_longopt)
{
register int j=i-1;
register int len_larg=(int)strlen(larg_longopt);
if (!strncmp(ptr_lopt->largs[j], larg_longopt, len_larg))
{
if (len_larg == (int)strlen(ptr_lopt->largs[j]))
/*
Exact match
*/
ok = TRUE;
else
{
while ( !ok
&& (ptr_lopt->largs[i] != NULL))
{
if ( !strncmp(ptr_lopt->largs[i], larg_longopt, len_larg)
&& (len_larg == (int)strlen(ptr_lopt->largs[i])))
/*
Exact match
*/
ok = TRUE;
i++;
}
}
if (!ok)
{
auto Bool ambig=FALSE;
/*
Given SPECIAL argument doesn't match exactly,
so try to detect whether its ambiguous
*/
i = j + 1;
while ( !ambig
&& (ptr_lopt->largs[i] != NULL))
{
if (!strncmp(ptr_lopt->largs[i], larg_longopt, len_larg))
ambig = TRUE;
i++;
}
if (ambig)
{
*longopt_symbolic = ptr_lopt->symbolic_name;
/*
Error, given SPECIAL argument is ambiguous.
*/
return(6);
}
else
{
/*
Given SPECIAL argument is valid!
*/
ok = TRUE;
i = j + 1;
}
}
}
else
ptr_char = ptr_lopt->largs[i++];
}
else
ptr_char = ptr_lopt->largs[i++];
}
if (!ok)
{
*longopt_symbolic = ptr_lopt->symbolic_name;
/*
Error, given SPECIAL argument not found in `lopt' structure member `largs'.
*/
return(5);
}
i--;
if (ptr_lopt->short_name[0] == NULL)
{
/*
Return the completed `long_name' with a completed SPECIAL argument;
the format of returned `longopt' is like: foo=BAR
*/
strcpy(longopt, ptr_lopt->long_name);
strcat(longopt, LARG_SEP);
strcat(longopt, ptr_lopt->largs[i]);
*longopt_symbolic = ptr_lopt->symbolic_name;
return(-2);
}
/*
Return the corresponding `short_name' with a converted SPECIAL argument;
the format of returned `longopt' is like: fooBAR
*/
strcpy(longopt, ptr_lopt->short_name[i]);
}
free(larg_longopt);
}
}
else
/*
Error, `longopt' not member of field `long_name' of `lopt' structure.
*/
return(2);
}
else
/*
Error, `longopt' not member of field `long_name' of `lopt' structure.
*/
return(2);
}
else
/*
Error, first entry in `lopt' structure member `long_name' greater than delivered `longopt'.
*/
return(2);
*longopt_symbolic = ptr_lopt->symbolic_name;
return(0);
}
#ifdef ANSI_PROTO
LOCAL void
rearrange_argv (const char *opt_list,
int *argc,
char *argv[])
#else /* !ANSI_PROTO */
LOCAL void
rearrange_argv (opt_list, argc, argv)
const char *opt_list;
int *argc;
char *argv[];
#endif /* !ANSI_PROTO */
/*
Rearranges `*argv[]' internally.
this means, all short-style options which need an argument,
which is separated by a whitespace character in command line
from the short option character, e.g. `-x foo' is concatenated
to `-xfoo'. the short option characters which need an argument
are given in `*opt_list'. this function sets given `*argc' to
the "new" rearranged amount of arguments stored in `*argv[]'.
*/
{
register int i=*argc-1;
register int n=1;
auto char **ptr_argv=argv;
auto char **ptr2_argv;
auto Bool is_modified;
while (i)
{
/*
Generally skip `argv[0]'
*/
ptr_argv++;
is_modified = FALSE;
if ( **ptr_argv == *SWITCH
|| **ptr_argv == *SWITCH2)
{
/*
Found an option in `*argv[]'
(either a long-style option or a short-style option).
*/
(*ptr_argv)++;
if ( **ptr_argv
&& (**ptr_argv != *SWITCH))
{
/*
Short-style option given, e.g. `-x' or `-Xfoo' or `-x bar'
*/
if (strchr(opt_list, **ptr_argv) != (char *)NULL)
{
/*
The option character is found in `opt_list',
this means this option needs an argument.
*/
if (i > 1)
{
/*
We are not working on last option stored in `*argv[]'.
*/
(*ptr_argv)++;
/*
Check if option doesn't have a its argument already
unseparated by a whitespace character in command line,
e.g. is not like this `-Xfoo' option.
*/
if (!**ptr_argv)
{
/*
Check if option is trailed by a needed argument,
which is the next argument in `*argv[]', e.g. `-x bar'
*/
(*ptr_argv)--;
(*ptr_argv)--;
ptr2_argv = ptr_argv;
ptr2_argv++;
/*
Check whether this next argument in `*argv[]' is an option
*/
if ( (**ptr2_argv != RSP_CHAR)
#if USE_RC
&& (**ptr2_argv != RC_ADATE_CHAR)
#endif
)
{
if ( ( **ptr2_argv == *SWITCH
|| **ptr2_argv == *SWITCH2)
&& (strlen(*ptr2_argv) <= 2))
/*
Next argument is definitely a simple short-style option
without a given modifier, e.g. `-x' or `/x'
*/
(*ptr_argv)++;
else
{
/*
Next argument is no option, concatenate the short
style option character and its needed argument
*/
i--;
argv[n] = (char *)my_realloc (argv[n], strlen(*ptr_argv)+strlen(*ptr2_argv)+1,
124, __FILE__, __LINE__ -1,
"argv[n]", 0);
strcpy(argv[n], *ptr_argv);
strcat(argv[n], *ptr2_argv);
ptr_argv++;
is_modified = TRUE;
}
}
else
(*ptr_argv)++;
}
else
(*ptr_argv)--;
}
}
}
}
else
(*ptr_argv)++;
if (!is_modified)
{
/*
Unmodified argument found in `*argv[]';
this means, the argument we work on here is
either a short-style option, which needs an argument, which isn't given
or a short-style option, which already contains its argument like `-Xfoo'
or a simple short-style option like `-x'
or a long-style option like `--foo'...
or a command (an argument not leaded by a '-', '/', '@' or '%' character.
*/
(*ptr_argv)--;
argv[n] = (char *)my_realloc (argv[n], strlen(*ptr_argv)+1,
124, __FILE__, __LINE__ -1,
"argv[n]", 0);
strcpy(argv[n], *ptr_argv);
}
n++;
i--;
}
*argc = n;
}
#ifdef ANSI_PROTO
LOCAL void
check_command_line (int argc,
char *argv[])
#else /* !ANSI_PROTO */
LOCAL void
check_command_line (argc, argv)
int argc;
char *argv[];
#endif /* !ANSI_PROTO */
/*
Gets the arguments from the command line
*/
{
register int opt_error=0;
auto int i;
auto int lopt_help;
auto char *option=(char *)NULL;
auto Bool is_longopt;
auto Bool skip_option;
#if USE_RC
auto Bool further_check;
#endif
/*
Work on arguments found in command line
*/
while (argc > 1)
{
option = *++argv;
/*
If leading switch character is found,
check the command line for options
*/
if ( *option == *SWITCH
|| *option == *SWITCH2)
{
is_longopt = FALSE;
/*
Check the command line for options
*/
for (option++ ; *option ; option++)
{
skip_option = FALSE;
#if USE_RC
further_check = FALSE;
#endif
/*
Check for long options, e.g. --help ...
*/
if (*option == *SWITCH)
{
is_longopt = TRUE;
option++;
if (*option)
{
i = 0;
strncpy(s2, option, MAXLEN+1);
s2[MAXLEN] = '\0';
/*
Set only option part to lower case
*/
while ( s2[i]
&& (s2[i] != *LARG_SEP))
{
s2[i] = (char)tolower(s2[i]);
i++;
}
opt_error = eval_longopt (s2, &lopt_id);
if (opt_error < 1)
{
opt_error = 0;
#if USE_RC
if (lopt_id == SYM_HIDDEN)
rc_nzero_ldvar_flag = TRUE;
else
{
#endif
if (lopt_id == SYM_DEBUG)
; /* Void, --debug[=0...WARN_LVL_MAX] already managed in main() */
else
{
option = s2;
/*
Now we have decoded a long option into the according short option form...
let's JUMP to that part where the short options are processed (to JUMP
isn't very good coding style, but its the easiest to do now =:^)
*/
goto LABEL_short_option;
}
#if USE_RC
}
#endif
}
}
else
/*
Error, no long option name given
(this case can't occur anymore!!)
*/
opt_error = 2;
skip_option = TRUE;
}
else
/*
Check for short options...
*/
LABEL_short_option:
switch (*option)
{
case '?':
case 'h':
help_flag = TRUE;
option++;
if (*option)
{
if ( *option == '?'
|| *option == 'h')
{
ext_help_flag = TRUE;
lopt_help = SYM_NIL;
option++;
if ( *option
&& is_longopt)
{
strncpy(s3, option, MAXLEN+1);
s3[MAXLEN] = '\0';
/*
Set only option part to lower case
*/
i = 0;
while ( s3[i]
&& (s3[i] != *LARG_SEP))
{
s3[i] = (char)tolower(s3[i]);
i++;
}
/*
Check out if an argument to long option is given
*/
(void)eval_longopt (s3, &lopt_help);
if (lopt_help == SYM_NIL)
/*
Error, no help related to this argument found
*/
opt_error = 5;
}
else
if (*option)
/*
Error, invalid option modifier given
*/
opt_error = 2;
}
else
/*
Error, no semi-long option name -?? or -hh given
*/
opt_error = 2;
}
skip_option = TRUE;
break;
case 'L':
option++;
if (!*option)
license_flag=skip_option = TRUE;
else
/*
Error, invalid option modifier given
*/
opt_error = 2;
break;
case 'V':
option++;
if (!*option)
version_flag=skip_option = TRUE;
else
/*
Error, invalid option modifier given
*/
opt_error = 2;
break;
case 'R':
option++;
if (*option)
{
rsp_filename = (char *)my_realloc (rsp_filename, strlen(option)+1,
124, __FILE__, __LINE__ -1,
"rsp_filename", 0);
strcpy(rsp_filename, option);
}
else
/*
Error, option character is not trailed by an argument
*/
opt_error = 4;
skip_option = TRUE;
break;
#ifdef GCAL_SHELL
case 'S':
option++;
if (*option)
{
shl_filename = (char *)my_realloc (shl_filename, strlen(option)+1,
124, __FILE__, __LINE__ -1,
"shl_filename", 0);
strcpy(shl_filename, option);
}
else
/*
Error, option character is not trailed by an argument
*/
opt_error = 4;
skip_option = TRUE;
break;
#endif /* GCAL_SHELL */
#if USE_RC
case 'v':
/*
If the define_global_date_variable option -v<def:def...> is given,
skip/ignore that option because it's already managed by main()
only check if NO definitions are given because this is an error...
*/
option++;
if (!*option)
/*
Error, option character is not trailed by an argument
*/
opt_error = 4;
skip_option = TRUE;
break;
#endif /* USE_RC */
case 'u':
option++;
if (!*option)
suppr_cal_flag=skip_option = TRUE;
else
/*
Error, invalid option modifier given
*/
opt_error = 2;
break;
#if USE_PAGER
case 'p':
option++;
if (!*option)
pager_flag=skip_option = TRUE;
else
/*
Error, invalid option modifier given
*/
opt_error = 2;
break;
#endif
case 'H':
option++;
if (!*option)
/*
Error, option character is not trailed by an argument
*/
opt_error = 4;
else
{
i = (int)strlen(option);
/*
Check if special argument `no' is given
if only `long-option=NO' instead of
`short-optionNO' too should be valid,
extend following if() like: if (is_longopt && ...
*/
if ( (i == 2)
&& (tolower(*option) == 'n')
&& (tolower(*(option+1)) == 'o'))
highlight_flag = FALSE;
else
/*
Check if special argument `yes' is given
if only `long-option=YES' instead of
`short-optionYES' too should be valid,
extend following if() like: if (is_longopt && ...
*/
if ( (i == 3)
&& (tolower(*option) == 'y')
&& (tolower(*(option+1)) == 'e')
&& (tolower(*(option+2)) == 's'))
{
highlight_flag = TRUE;
is_tty = (int)TRUE;
}
else
{
hl_seq = (char *)my_realloc (hl_seq, strlen(option)+1,
124, __FILE__, __LINE__ -1,
"hl_seq", 0);
strcpy(hl_seq, option);
highlight_flag = TRUE;
}
}
skip_option = TRUE;
break;
case 'i':
suppr_cal_flag = FALSE;
option++;
#if USE_GER
special_calsheet_flag = TRUE;
#else /* !USE_GER */
special_calsheet_flag = FALSE;
#endif /* !USE_GER */
if (*option)
{
if (*option == '-')
{
switch_back_flag = TRUE;
option++;
if (*option)
/*
Error, option character is trailed by invalid argument
*/
opt_error = 5;
}
else
/*
Error, option character is trailed by invalid modifier
*/
opt_error = 5;
}
else
switch_back_flag = FALSE;
option--;
break;
case 'n':
case 'N':
holiday_flag = TRUE;
hd_sort_des_flag = FALSE;
hd_legal_days_only = (Bool)((*option == 'N') ? TRUE : FALSE);
option++;
if (*option)
{
if (*option == *DES_LIT)
hd_sort_des_flag = TRUE;
else
/*
Error, option character is trailed by invalid modifier
*/
opt_error = 5;
}
skip_option = TRUE;
break;
case 'X':
option++;
if (!*option)
{
hd_title_flag = FALSE;
skip_option = TRUE;
}
else
/*
Error, invalid option modifier given
*/
opt_error = 2;
break;
case 'j':
option++;
if (!*option)
{
cal_julian_flag = TRUE;
cal_both_dates_flag = FALSE;
}
else
{
if (*option == 'b')
{
option++;
if (!*option)
{
cal_julian_flag = FALSE;
cal_both_dates_flag = TRUE;
}
else
/*
Error, option character is trailed by an invalid modifier
*/
opt_error = 5;
}
else
{
switch (*option)
{
case 'n':
option++;
if (!*option)
hd_julian_flag = TRUE;
else
if (*option == 'b')
hd_both_dates_flag = TRUE;
else
/*
Error, option character is trailed by an invalid modifier
*/
opt_error = 5;
break;
#if USE_RC
case 'c':
option++;
if (!*option)
rc_julian_flag = TRUE;
else
if (*option == 'b')
rc_both_dates_flag = TRUE;
else
/*
Error, option character is trailed by an invalid modifier
*/
opt_error = 5;
break;
#endif
default:
/*
Error, option character is trailed by an invalid modifier
*/
opt_error = 5;
}
}
}
if (!*option)
option--;
break;
case 'b':
year_flag = TRUE;
option++;
if (*option == '0')
{
while (*option == '0')
option++;
if (!*option)
option--;
}
out_rows = my_atoi (option);
if ( out_rows > MONTH_MAX
|| out_rows < MONTH_MIN
|| out_rows == 5
|| ( (out_rows > 6)
&& (out_rows < MONTH_MAX)))
{
if (!*option)
/*
Error, option character is not trailed by an argument
*/
opt_error = 4;
else
/*
Error, option character is trailed by an invalid argument
*/
opt_error = 5;
}
else
skip_option = TRUE;
suppr_cal_flag = FALSE;
break;
case 's':
option++;
if (!*option)
/*
Error, option character is not trailed by an argument
*/
opt_error = 4;
else
{
start_day = my_atoi (option);
/*
Check for delivered weekday name
*/
if (!start_day)
start_day = compare_d_m_name (option, DAy);
if ( !start_day
&& isdigit(*option))
start_day = -1; /* Special value */
else
if ( start_day > DAY_MAX
|| start_day < DAY_MIN)
/*
Error, option character is trailed by an invalid argument
*/
opt_error = 5;
suppr_cal_flag = FALSE;
}
skip_option = TRUE;
break;
#if USE_RC
case 'f':
case 'F':
if (*option == 'F')
rc_all_dates_flag = TRUE;
option++;
if (*option)
{
rc_filename = (char *)my_realloc (rc_filename, strlen(option)+1,
124, __FILE__, __LINE__ -1,
"rc_filename", 0);
strcpy(rc_filename, option);
rc_use_flag=skip_option = TRUE;
}
else
/*
Error, option character is not trailed by an argument
*/
opt_error = 4;
break;
case 'g':
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
{
option++;
if (*option)
{
rc_grp_sep = (char *)my_realloc (rc_grp_sep, strlen(option)+1,
124, __FILE__, __LINE__ -1,
"rc_grp_sep", 0);
strcpy(rc_grp_sep, option);
}
else
if (rc_grp_sep == (char *)NULL)
rc_grp_sep = (char *)RC_GROUP_SEP;
}
skip_option = TRUE;
break;
case 'a':
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
rc_enable_fn_flag = TRUE;
break;
case 'd':
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
rc_have_today_in_list = 1;
break;
case 'e':
case 'E':
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
{
if (*option == 'E')
{
rc_enable_hdl_flag = TRUE;
rc_enable_hda_flag = FALSE;
}
else
{
rc_enable_hdl_flag = FALSE;
rc_enable_hda_flag = TRUE;
}
}
break;
case 'o':
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
rc_omit_date_flag = TRUE;
break;
case 'l':
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
/*
Assume the user wants to have a list
of periods instead of a single period!
*/
rc_period_list = TRUE;
break;
case 'k':
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
rc_weekno_flag = TRUE;
break;
case 'x':
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
rc_title_flag = FALSE;
break;
case 'z':
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
rc_count_flag = TRUE;
break;
case 'c':
case 'C':
rc_use_flag = TRUE;
if (*option == 'C')
rc_all_dates_flag = TRUE;
option++;
if (*option == *DES_LIT)
{
rc_sort_des_flag = TRUE;
while (*option == *DES_LIT)
option++;
}
option--;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case RC_HDY_CHAR:
case RC_NWD_CHAR:
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
{
register int act_is_leap_year=(days_of_february (act_year)==29);
auto int wmax=WEEK_MAX;
auto char dvar='\0';
auto Bool nth_day_of_year_flag=FALSE;
i = 0;
if (act_year == GREG_YEAR)
wmax = ((DAY_LAST + (days_of_february (GREG_YEAR) == 29)
- (GREG_L_DAY - GREG_F_DAY + 1)) / DAY_MAX) + 1;
rc_clean_flags ();
rc_period = 0;
rc_period_flag = TRUE;
/*
Before i forget... all mode specifying characters
('n', 'd' or 'w') may be given in upper or lower
case, i.e. they are managed case insensitive!
*/
/*
Check if @<e|`dvar'>[[-]<n>[`ww[w]']] or
*d|w<n>[`ww[w]'] is given
*/
if ( *option == RC_HDY_CHAR
|| *option == RC_NWD_CHAR)
dvar = *option;
else
/*
Compute period for <n>d
*/
rc_period = atoi(option);
if (!dvar)
{
auto char *ptr_char;
/*
Check if <n>+ is given
*/
rc_forwards_flag = (Bool)(strchr(option, *ASC_LIT) != (char *)NULL);
/*
Check if <n>- is given
*/
rc_backwards_flag = (Bool)(strchr(option, *DES_LIT) != (char *)NULL);
/*
Check if <n>w is given
*/
ptr_char = strrchr(option, 'w');
if (ptr_char == (char *)NULL)
ptr_char = strrchr(option, 'W');
if (ptr_char != (char *)NULL)
{
ptr_char++;
if (!*ptr_char)
rc_week_year_flag = TRUE;
}
/*
Check if <n>d is given
*/
ptr_char = strrchr(option, 'd');
if (ptr_char == (char *)NULL)
ptr_char = strrchr(option, 'D');
if (ptr_char != (char *)NULL)
{
ptr_char++;
if (!*ptr_char)
nth_day_of_year_flag = TRUE;
}
i = (int)rc_forwards_flag + rc_backwards_flag
+ rc_week_year_flag + nth_day_of_year_flag;
}
/*
Compute period for <n>d
*/
if (rc_period == 999)
rc_period = DAY_LAST + act_is_leap_year;
if ( !dvar
&& ( i > 1
|| ( (rc_period > DAY_LAST+act_is_leap_year)
&& ( rc_forwards_flag
|| rc_backwards_flag
|| nth_day_of_year_flag))
|| ( rc_week_year_flag
&& (rc_period > wmax+1)
&& (rc_period != 99))))
/*
Error, illegal warning period modifier given
*/
opt_error = 5;
else
{
/*
Found one of these warning period modifiers:
@<e|`dvar'>[[-]<n>[`ww[w]']]
*d|w<n>[`ww[w]']
`mmdd'
`mmww[w]'<n>
*/
if ( !rc_week_year_flag
&& !rc_forwards_flag
&& !rc_backwards_flag)
{
auto int y=act_year;
auto int n;
auto char hc;
auto Bool is_weekday_mode;
if (!nth_day_of_year_flag)
{
sprintf(s2, "%0*d%s", len_year_max, y, option);
/*
rc_get_date() arguments `wmax', `hc' and `i' are dummys
only and must be given. they are not respected!
*/
(void)rc_get_date (s2, &is_weekday_mode, &day, &month, &y, &n, &wmax,
&hc, &i, &i, &hc, 0, &hc, FALSE);
if (y != -1)
{
if (!dvar)
{
/*
`mmww[w]'<n> or `mmdd' given
*/
if (!month)
month = act_month;
if ( month < MONTH_MIN
|| month > MONTH_MAX)
/*
Error, invalid month given
*/
opt_error = 5;
else
{
i = dvec[month-1];
if (month == 2)
i += act_is_leap_year;
if (is_weekday_mode)
{
/*
`mmww[w]'<n> given
*/
if (n == 9)
day = eval_holiday (i, month, act_year, day, FALSE);
else
{
day = eval_holiday (DAY_MIN, month, act_year, day, TRUE);
day += (DAY_MAX * (n - 1));
if (day > i)
/*
Error, month contains no such "n'th weekday of month"
*/
opt_error = 5;
else
{
/*
Now check if given date is valid
*/
if ( !day
|| !valid_date (day, month, act_year))
/*
Error, invalid date given
*/
opt_error = 5;
}
}
}
else
{
/*
`mmdd' given
*/
if (day == 99)
day = i;
if (!day)
day = act_day;
if ( day < DAY_MIN
|| day > i)
/*
Error, invalid day given
*/
opt_error = 5;
}
}
}
else
if ( !day
|| !month)
/*
Error, either invalid date variable
or invalid mode specifier given (not d|w)
*/
opt_error = 5;
if (!opt_error)
rc_period = day_of_year (day, month, act_year);
}
else
/*
Error, invalid date given
*/
opt_error = 5;
}
else
if (!rc_period)
/*
Error, zero date is invalid
*/
opt_error = 5;
if (!opt_error)
{
i = day_of_year (act_day, act_month, act_year);
if (rc_period >= i)
{
rc_forwards_flag = TRUE;
rc_period -= i;
}
else
{
rc_backwards_flag = TRUE;
rc_period = i - rc_period;
}
}
}
else
{
/*
<n>w|+|- given
*/
i = 0;
while (isdigit(*option))
{
i++;
option++;
}
option--;
if ( !rc_period
&& !rc_week_year_flag)
/*
Error, zero lenght date of warning period given
*/
opt_error = 5;
else
further_check = TRUE;
}
}
}
skip_option = TRUE;
break;
case 't':
case 'T':
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
{
rc_clean_flags ();
rc_tomorrow_flag = TRUE;
if (*option == 'T')
rc_all_dates_flag = TRUE;
option++;
if (*option)
/*
Error, invalid option modifier given
*/
opt_error = 2;
skip_option = TRUE;
}
break;
case 'w':
case 'W':
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
{
rc_clean_flags ();
rc_week_flag = TRUE;
if (*option == 'W')
rc_all_dates_flag = TRUE;
further_check = TRUE;
}
break;
case 'm':
case 'M':
# ifdef GCAL_EMAIL
if ( (*option == 'm')
&& *(option+1)
&& (*(option+1) != *ASC_LIT)
&& (*(option+1) != *DES_LIT))
{
option++;
email_adr = (char *)my_realloc (email_adr, strlen(option)+1,
124, __FILE__, __LINE__ -1,
"email_adr", 0);
strcpy(email_adr, option);
skip_option = TRUE;
}
else
# endif
if ( !rc_use_flag
&& !is_longopt)
# ifdef GCAL_EMAIL
/*
Error, option character is not trailed by an argument
*/
opt_error = 4;
# else /* !GCAL_EMAIL */
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
# endif /* !GCAL_EMAIL */
else
{
rc_clean_flags ();
rc_month_flag = TRUE;
if (*option == 'M')
rc_all_dates_flag = TRUE;
further_check = TRUE;
}
break;
case 'y':
case 'Y':
if ( !rc_use_flag
&& !is_longopt)
/*
Error, given stand-alone option actually invalid
*/
opt_error = 2;
else
{
rc_clean_flags ();
rc_year_flag = TRUE;
if (*option == 'Y')
rc_all_dates_flag = TRUE;
further_check = TRUE;
}
break;
#else /* !USE_RC */
case 'm':
# ifdef GCAL_EMAIL
option++;
if (*option)
{
email_adr = (char *)my_realloc (email_adr, strlen(option)+1,
124, __FILE__, __LINE__ -1,
"email_adr", 0);
strcpy(email_adr, option);
skip_option = TRUE;
}
else
# endif
/*
Error, option character is not trailed by an argument
*/
opt_error = 4;
break;
#endif /* !USE_RC */
default:
/*
Error, any unmanaged options are always invalid
*/
opt_error = 2;
}
#if USE_RC
if ( further_check
&& !opt_error)
{
option++;
if (*option)
{
rc_week_year_flag = (Bool)(tolower(*option) == 'w');
rc_forwards_flag = (Bool)(*option == *ASC_LIT);
rc_backwards_flag = (Bool)(*option == *DES_LIT);
option++;
if ( *option
|| ( !rc_week_year_flag
&& !rc_forwards_flag
&& !rc_backwards_flag))
/*
Error, either argument is trailed by an illegal character
or no mode specifying character (w|+|-) is given
*/
opt_error = 2;
}
skip_option = TRUE;
}
#endif /* USE_RC */
if (opt_error)
{
switch (opt_error)
{
#if USE_GER
case 1:
sprintf(s, "%s: Option `%s' ist nicht eindeutig",
prgr_name, *argv);
break;
case 2:
if (is_longopt)
sprintf(s, "%s: Option ist unbekannt `%s'",
prgr_name, *argv);
else
sprintf(s, "%s: Option ist ung"UE"ltig -- %s",
prgr_name, *argv+1);
break;
case 3:
sprintf(s, "%s: Option `%s' erlaubt kein Argument",
prgr_name, *argv);
break;
case 4:
if (is_longopt)
sprintf(s, "%s: Option `%s' ben"OE"tigt ein Argument",
prgr_name, *argv);
else
sprintf(s, "%s: Option ben"OE"tigt ein Argument -- %s",
prgr_name, *argv+1);
break;
case 5:
sprintf(s, "%s: Option mit unzul"AE"ssigem Argument -- %s",
prgr_name, *argv);
break;
case 6:
sprintf(s, "%s: Option mit nicht eindeutigem Argument -- %s",
prgr_name, *argv);
#else /* !USE_GER */
case 1:
sprintf(s, "%s: option `%s' is ambiguous",
prgr_name, *argv);
break;
case 2:
if (is_longopt)
sprintf(s, "%s: unrecognized option `%s'",
prgr_name, *argv);
else
sprintf(s, "%s: invalid option -- %s",
prgr_name, *argv+1);
break;
case 3:
sprintf(s, "%s: option `%s' doesn't allow an argument",
prgr_name, *argv);
break;
case 4:
if (is_longopt)
sprintf(s, "%s: option `%s' requires an argument",
prgr_name, *argv);
else
sprintf(s, "%s: option requires an argument -- %s",
prgr_name, *argv+1);
break;
case 5:
sprintf(s, "%s: option with invalid argument -- %s",
prgr_name, *argv);
break;
case 6:
sprintf(s, "%s: option with ambiguous argument -- %s",
prgr_name, *argv);
#endif /* !USE_GER */
break;
default:
my_error (opt_error, "", 0, "", 0); /* This case must be an Internal error */
}
fprintf(stderr, "%s\n%s\n", s, usage_msg ());
put_longopt_description (stderr);
S_NEWLINE(stderr);
exit(126);
}
if (skip_option)
{
while (*option)
option++;
option--;
}
}
argc--;
}
else
{
#if USE_RC
/*
If actual date modifier %... is given, skip/ignore complete option
because it's already managed by the main() function
*/
if (**argv == RC_ADATE_CHAR)
argc--;
else
#endif
break;
}
}
if ( help_flag
|| license_flag
|| version_flag)
{
#if USE_PAGER
/*
No program output yet and output goes to a tty:
set the standard stream buffers to unbuffered mode,
then get actual settings of the tty (needed if paging is wanted)
*/
if ( is_tty1
&& is_tty2
# ifdef GCAL_EPAGER
&& (ext_pager == (char *)NULL)
# endif
)
{
setbuf(stdout, (char *)NULL);
setbuf(stdin, (char *)NULL);
get_tty_scr_size (&tty_rows, &tty_cols);
}
#endif /* USE_PAGER */
/*
Get the highlighting sequences of the terminal
*/
get_tty_hls (hl_seq);
#ifdef GCAL_EPAGER
if ( is_tty1
&& is_tty2
&& pager_flag
&& (ext_pager != (char *)NULL))
{
child_pid = fork();
switch (child_pid)
{
case -1:
/*
Error, fork() fails
*/
my_error (110, __FILE__, __LINE__ -7, "fork()", 0);
case 0:
/*
Child process (read from pipe):
connect pipe-stdin to sys-stdin in a safe way
and launch external pager
*/
close(pipe_fd[1]);
if (pipe_fd[0])
{
close(0);
dup(pipe_fd[0]);
close(pipe_fd[0]);
}
execlp(ext_pager, ext_pager, (char *)NULL);
/*
Error, execlp() fails (this line should never be executed)
*/
sprintf(s, "execlp(%s)", ext_pager);
my_error (110, __FILE__, __LINE__ -5, s, 0);
default:
/*
Parent process (write to pipe):
connect pipe-stdout to sys-stdout in a safe way
and initiate action
*/
close(pipe_fd[0]);
if (pipe_fd[1] != 1)
{
close(1);
if (!dup(pipe_fd[1]))
{
dup(pipe_fd[1]);
close(0);
}
close(pipe_fd[1]);
}
}
}
#endif /* GCAL_EPAGER */
if (help_flag)
{
if (ext_help_flag)
/*
Extended help pages (--long-help[=ARG] or -hh or -?? or -h? or -?h)
*/
my_extended_help (stdout, lopt_help);
else
/*
Basic help page (--help or -h or -?)
*/
my_basic_help (stdout);
}
else
{
/*
Store program name and some information to global text buffer `s2'
*/
strncpy(s, rcsid+11, 25);
s[25] = '\0';
sprintf(s2, "%s%s", prgr_name, s);
if (license_flag)
/*
License text (--license or -L)
*/
my_license (stdout, s2);
else
if (version_flag)
/*
Version text (--version or -V)
*/
my_version (stdout, s2);
}
#ifdef GCAL_EPAGER
if ( is_tty1
&& is_tty2
&& pager_flag
&& (ext_pager != (char *)NULL))
{
/*
We work unbuffered in this case so we have to flush stdout buffer
for showing all contents of it
*/
fflush(stdout);
/*
And reconnect the sys-stdin/sys-stdout file descriptors
*/
close(0);
dup(sys_fd[0]);
close(1);
dup(sys_fd[1]);
/*
And wait until child has performed all action
*/
while (wait((pid_t *)NULL) != child_pid)
;
/*
Reset SIGPIPE signal
*/
signal(SIGPIPE, SIG_DFL);
}
#endif /* GCAL_EPAGER */
exit(EXIT_STAT_HLP);
}
month = 0;
if (argc > 1)
{
auto Bool is_list=FALSE;
auto Bool is_range=FALSE;
auto Bool month_set=FALSE;
auto Bool year_sep_found=FALSE;
for ( ; argc > 1 ; argc--, argv++)
{
if (!month)
{
option = *argv;
if (*option == *MONTH3_LIT)
break;
else
while (*option)
{
if ( *option == *MLIST_SEP
|| *option == *YLIST_SEP)
is_list = TRUE;
else
if ( *option == *MRANGE_SEP
|| *option == *YRANGE_SEP)
is_range = TRUE;
else
if (*option == *YEAR_SEP)
year_sep_found = TRUE;
else
if (*option == *FYEAR_SEP)
is_fiscal_year = TRUE;
option++;
}
option = *argv;
if ( !is_list
&& !is_range
&& !year_sep_found
&& !is_fiscal_year
&& !my_atoi (option))
{
month = compare_d_m_name (option, MOnth);
if (month)
{
month_set = TRUE;
continue;
}
}
}
if (!month)
{
build_month_list (argv);
if (!*month_list.month)
month = atoi(*argv);
else
month = *month_list.month;
if ( month < MONTH_MIN
|| month > MONTH_MAX)
{
if (!is_fiscal_year)
year = month;
month = 0;
break;
}
}
else
if (!year)
{
if ( *month_list.year
&& ( is_list
|| is_range))
year = *month_list.year;
else
year = my_atoi (*argv);
}
}
/*
"." or ".." or ".+" or ".-" argument found:
3 month mode wanted
*/
if (*option == *MONTH3_LIT)
{
register int len=(int)strlen(option);
if (len <= 2)
{
if (*(option + 1) == *MONTH3_LIT)
is_3month_mode2 = TRUE;
else
is_3month_mode = TRUE;
is_fiscal_year = TRUE;
year_flag = FALSE;
month = act_month;
/*
Check if an explicit year trails the 3 month mode command
*/
if (argc > 2)
{
argv++;
year = atoi(*argv);
if (!year)
year = act_year;
}
else
year = act_year;
if (is_3month_mode)
{
/*
Either "." or ".+" or ".-" 3 month mode command found
*/
if (!*(option + 1))
{
/*
"." 3 month mode command found
*/
month--;
if (!month)
{
month = MONTH_MAX;
year--;
}
}
else
if (*(option + 1) == *DES_LIT)
{
/*
".-" 3 month mode command found
*/
month -= 2;
if (month < MONTH_MIN)
{
month = MONTH_MAX + month;
year--;
}
}
else
if (*(option + 1) == *ASC_LIT)
/*
".+" 3 month mode command found
*/
; /* Void, nothing to do! */
else
{
/*
Error, invalid modifier trails the dot character ->
print default month calendar only
*/
is_fiscal_year = FALSE;
year = act_year;
month = act_month;
}
if (year < YEAR_MIN)
{
year = YEAR_MIN;
month = act_month;
}
}
else
/*
".." 3 month mode command found
*/
month = ((month + 1) - ((month - 1) % 3)) - 1;
}
}
else
if ( month
&& !year
&& !month_set
&& !*month_list.month
&& !is_fiscal_year)
{
year = month;
month = 0;
}
}
}
#ifdef ANSI_PROTO
LOCAL void
build_month_list (char *argv[])
#else /* !ANSI_PROTO */
LOCAL void
build_month_list (argv)
char *argv[];
#endif /* !ANSI_PROTO */
/*
If more than a single month/year is wanted, fill the global
data structure `month_list'; used in print_calendar();
according the values found in the command line
*/
{
register int i;
register int j;
auto const char *option;
auto Bool is_list=FALSE;
auto Bool is_range=FALSE;
auto Bool year_sep_found=FALSE;
auto Bool buf_is_ext_year;
option = *argv;
for ( ; *option && !is_list && !is_range ; option++)
if ( *option == *MLIST_SEP
|| *option == *YLIST_SEP)
{
is_list = TRUE;
if (*option == *YLIST_SEP)
is_ext_list=is_ext_year = TRUE;
}
else
if ( *option == *MRANGE_SEP
|| *option == *YRANGE_SEP)
{
is_range = TRUE;
if (*option == *YRANGE_SEP)
is_ext_range=is_ext_year = TRUE;
}
else
if (*option == *YEAR_SEP)
year_sep_found = TRUE;
buf_is_ext_year = is_ext_year;
if ( year_sep_found
|| ( is_fiscal_year
&& ( is_ext_list
|| is_ext_year
|| ( !is_list
&& !is_range)))
|| ( !is_fiscal_year
&& ( is_list
|| is_range)))
{
i = 0;
option = *argv;
while ( *option
&& (i < MONTH_MAX))
{
year_sep_found = FALSE;
j = 0;
while ( *option
&& !year_sep_found
&& ( ( !is_list
&& !is_range)
|| ( ( is_list
&& ( (*option != *MLIST_SEP)
&& (*option != *YLIST_SEP)))
|| ( is_range
&& ( (*option != *MRANGE_SEP)
&& (*option != *YRANGE_SEP))))))
{
year_sep_found = (Bool)( *option == *YEAR_SEP
|| *option == *FYEAR_SEP);
s[j++] = *option++;
}
if (year_sep_found)
s[j-1] = '\0';
else
s[j] = '\0';
if (!*s)
{
if (is_fiscal_year)
{
j = atoi(option);
if (j)
{
is_ext_year = FALSE;
month_list.month[i++] = act_month;
}
}
else
{
j = 0;
while (*option)
option++;
}
}
else
j = my_atoi (s);
if (is_ext_year)
{
if (is_fiscal_year)
{
if ( (j >= MONTH_MIN)
&& (j <= MONTH_MAX))
month_list.month[i++] = j;
else
{
/*
Argument a valid month name?
*/
j = compare_d_m_name (s, MOnth);
if (j)
month_list.month[i++] = j;
else
/*
At end of argument?
*/
if (!*option)
{
if ( is_ext_list
|| is_ext_range)
{
if (!is_ext_list)
month_list.month[i] = month_list.month[i-1];
else
month_list.month[i] = MONTH_MIN;
j = my_atoi (s);
if (j)
month_list.year[i++] = j;
else
month_list.month[i] = 0;
}
}
else
/*
Not at end of argument:
fiscal year list wanted and standard year given
*/
if (!year_sep_found)
{
j = my_atoi (s);
if (j)
month_list.month [i++] = j;
/*
Otherwise ignore given argument
*/
}
else
year_sep_found = FALSE;
}
}
else
{
if (year_sep_found)
{
/*
Error, extended year list/range given like
5/1999;may/7777... or 5/1999+may/7777
--> respect the year part of date only
*/
j = 0;
while ( *option
&& ( ( is_list
&& (*option != *YLIST_SEP))
|| ( is_range
&& (*option != *YRANGE_SEP))))
s[j++] = *option++;
s[j] = '\0';
j = my_atoi (s);
}
if (j)
month_list.month[i++] = j;
else
if (is_list)
month_list.month[i++] = act_year;
}
if (year_sep_found)
{
while ( *option == *YEAR_SEP
|| *option == *FYEAR_SEP)
option++;
if (!is_fiscal_year)
{
year_sep_found = FALSE;
while ( *option
&& ( ( is_list
&& (*option != *YLIST_SEP))
|| ( is_range
&& (*option != *YRANGE_SEP))))
option++;
}
}
}
else
if (*s)
{
if ( (j >= MONTH_MIN)
&& (j <= MONTH_MAX))
month_list.month[i++] = j;
else
{
j = compare_d_m_name (s, MOnth);
if (j)
month_list.month[i++] = j;
}
}
if (year_sep_found)
{
if (j)
{
j = 0;
while ( *option == *YEAR_SEP
|| *option == *FYEAR_SEP)
option++;
if ( !is_list
&& !is_range)
while (*option)
s[j++] = *option++;
else
if ( is_fiscal_year
&& ( is_ext_list
|| is_ext_range))
while ( *option
&& ( ( is_list
&& (*option != *YLIST_SEP))
|| ( is_range
&& (*option != *YRANGE_SEP))))
s[j++] = *option++;
else
while ( *option
&& ( ( is_list
&& (*option != *MLIST_SEP))
|| ( is_range
&& (*option != *MRANGE_SEP))))
s[j++] = *option++;
s[j] = '\0';
j = my_atoi (s);
if (j)
{
month_list.year[i-1] = j;
if ( is_list
&& !is_ext_range)
is_ext_list = TRUE;
else
if ( is_range
&& !is_ext_list)
is_ext_range = TRUE;
}
else
if (is_fiscal_year)
month_list.year[i-1] = act_year;
}
else
{
if (is_fiscal_year)
while ( *option
&& ( ( is_list
&& (*option != *YLIST_SEP))
|| ( is_range
&& (*option != *YRANGE_SEP))))
option++;
else
while ( *option
&& ( ( is_list
&& (*option != *MLIST_SEP))
|| ( is_range
&& (*option != *MRANGE_SEP))))
option++;
}
}
while ( *option == *MLIST_SEP
|| *option == *MRANGE_SEP
|| *option == *YLIST_SEP
|| *option == *YRANGE_SEP)
option++;
/*
Fiscal year list/range wanted and year list/range incomplete
--> avoid error
*/
if ( i
&& is_fiscal_year
&& !month_list.year[i-1])
{
month_list.year[i-1] = month_list.month[i-1];
month_list.month[i-1] = MONTH_MIN;
}
is_ext_year = buf_is_ext_year;
}
if ( is_range
&& !is_ext_range)
{
register int k;
/*
Fiscal year wanted and only month range given
--> avoid error
*/
if (is_fiscal_year)
is_ext_year = TRUE;
else
{
/*
Ok, compute month range and place it in list
*/
j = *month_list.month;
k = month_list.month[1];
i = 0;
while (month_list.month[i])
month_list.month[i++] = 0;
if ( !j
&& !k)
*month_list.month = act_month;
else
{
if (!j)
j = MONTH_MIN;
if (!k)
k = MONTH_MAX;
i = 0;
if (j > k)
for ( ; j >= k ; i++, j--)
month_list.month[i] = j;
else
for ( ; j <= k ; i++, j++)
month_list.month[i] = j;
}
}
}
/*
Fiscal-/ standard year wanted and invalid range
--> avoid error
*/
if ( is_ext_range
&& month_list.month[2])
month_list.month[1] = 0;
/*
Standard year wanted and year list/range incomplete
--> avoid error
*/
if ( !month_list.month[1]
&& ( is_ext_list
|| is_ext_range
|| is_ext_year))
{
is_ext_list=is_ext_range=is_ext_year = FALSE;
*month_list.month = act_month;
*month_list.year = act_year;
}
}
}
#ifdef ANSI_PROTO
LOCAL void
eliminate_invalid_data (void)
#else /* !ANSI_PROTO */
LOCAL void
eliminate_invalid_data ()
#endif /* !ANSI_PROTO */
/*
Eliminates invalid command line argument values
and sets some internal variables according to command line arguments
*/
{
/*
Correct month and year
*/
if ( !month
&& !year)
{
month = act_month;
year = act_year;
}
else
if ( year < YEAR_MIN
|| year > YEAR_MAX)
{
if ( month
&& year)
month = act_month;
year = act_year;
}
if ( year_flag
&& month)
month = 0;
if ( month
&& !*month_list.month)
*month_list.month = month;
if ( year
&& !*month_list.year)
*month_list.year = year;
/*
Set default amount of month rows and columns according to calendar format
*/
if ( is_3month_mode
|| is_3month_mode2)
{
/*
Set fixed amount of month rows and columns for 3 month mode
(-b<> flag is ignored)
*/
if (special_calsheet_flag)
{
if (cal_julian_flag)
{
out_rows = JI3_OUT_ROWS;
out_cols = JI3_OUT_COLS;
}
else
if (cal_both_dates_flag)
{
out_rows = BI3_OUT_ROWS;
out_cols = BI3_OUT_COLS;
}
else
{
out_rows = SI3_OUT_ROWS;
out_cols = SI3_OUT_COLS;
}
}
else
{
if (cal_julian_flag)
{
out_rows = J3_OUT_ROWS;
out_cols = J3_OUT_COLS;
}
else
if (cal_both_dates_flag)
{
out_rows = B3_OUT_ROWS;
out_cols = B3_OUT_COLS;
}
else
{
out_rows = S3_OUT_ROWS;
out_cols = S3_OUT_COLS;
}
}
}
else
{
/*
Set default amount of month columns according to calendar format
*/
if (special_calsheet_flag)
{
if (cal_julian_flag)
out_cols = JI_OUT_COLS;
else
if (cal_both_dates_flag)
out_cols = BI_OUT_COLS;
else
out_cols = SI_OUT_COLS;
}
else
{
if (cal_julian_flag)
out_cols = J_OUT_COLS;
else
if (cal_both_dates_flag)
out_cols = B_OUT_COLS;
else
out_cols = S_OUT_COLS;
}
/*
Set amount of month cols according to calendar format
*/
switch (out_rows)
{
case 1:
out_cols = MONTH_MAX;
break;
case 2:
out_cols = 6;
break;
case 3:
out_cols = 4;
break;
case 4:
out_cols = 3;
break;
case 6:
out_cols = 2;
break;
case 12:
out_cols = MONTH_MIN;
break;
default:
/*
Set default amounts of month rows according to calendar format
*/
if (special_calsheet_flag)
{
if (cal_julian_flag)
out_rows = JI_OUT_ROWS;
else
if (cal_both_dates_flag)
out_rows = BI_OUT_ROWS;
else
out_rows = SI_OUT_ROWS;
}
else
{
if (cal_julian_flag)
out_rows = J_OUT_ROWS;
else
if (cal_both_dates_flag)
out_rows = B_OUT_ROWS;
else
out_rows = S_OUT_ROWS;
}
}
}
/*
Set the single day format length according to mode
*/
if (cal_julian_flag)
fmt_len = 4;
else
if (cal_both_dates_flag)
fmt_len = 8;
else
fmt_len = 3;
/*
Set starting day of week if not set by command line argument
(special value -1 found)
*/
if (start_day < 0)
start_day = weekday_of_date (act_day, act_month, act_year);
else
if (!start_day)
#if USE_GER
start_day = DAY_MIN;
#else /* !USE_GER */
start_day = DAY_MAX;
#endif /* !USE_GER */
}